home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095s.zip / DISASM.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  19KB  |  670 lines

  1. /* disasm.c   where all the _work_ gets done in the Netwide Disassembler
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * initial version 27/iii/95 by Simon Tatham
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include "nasm.h"
  15. #include "disasm.h"
  16. #include "sync.h"
  17. #include "insns.h"
  18.  
  19. #include "names.c"
  20.  
  21. extern struct itemplate **itable[];
  22.  
  23. /*
  24.  * Flags that go into the `segment' field of `insn' structures
  25.  * during disassembly.
  26.  */
  27. #define SEG_RELATIVE 1
  28. #define SEG_32BIT 2
  29. #define SEG_RMREG 4
  30. #define SEG_DISP8 8
  31. #define SEG_DISP16 16
  32. #define SEG_DISP32 32
  33. #define SEG_NODISP 64
  34. #define SEG_SIGNED 128
  35.  
  36. static int whichreg(long regflags, int regval) {
  37.     static int reg32[] = {
  38.     R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI };
  39.     static int reg16[] = {
  40.     R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI };
  41.     static int reg8[] = {
  42.     R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH };
  43.     static int sreg[] = {
  44.     R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, 0, 0 };
  45.     static int creg[] = {
  46.     R_CR0, 0, R_CR2, R_CR3, R_CR4, 0, 0, 0 };
  47.     static int dreg[] = {
  48.     R_DR0, R_DR1, R_DR2, R_DR3, 0, 0, R_DR6, R_DR7 };
  49.     static int treg[] = {
  50.     0, 0, 0, R_TR3, R_TR4, R_TR5, R_TR6, R_TR7 };
  51.     static int fpureg[] = {
  52.     R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7 };
  53.     static int mmxreg[] = {
  54.     R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7 };
  55.  
  56.     if (!(REG_AL & ~regflags))
  57.     return R_AL;
  58.     if (!(REG_AX & ~regflags))
  59.     return R_AX;
  60.     if (!(REG_EAX & ~regflags))
  61.     return R_EAX;
  62.     if (!(REG_DX & ~regflags))
  63.     return R_DX;
  64.     if (!(REG_CL & ~regflags))
  65.     return R_CL;
  66.     if (!(REG_CX & ~regflags))
  67.     return R_CX;
  68.     if (!(REG_ECX & ~regflags))
  69.     return R_ECX;
  70.     if (!(REG_CR4 & ~regflags))
  71.     return R_CR4;
  72.     if (!(FPU0 & ~regflags))
  73.     return R_ST0;
  74.     if (!(REG_CS & ~regflags))
  75.     return R_CS;
  76.     if (!((REGMEM|BITS8) & ~regflags))
  77.     return reg8[regval];
  78.     if (!((REGMEM|BITS16) & ~regflags))
  79.     return reg16[regval];
  80.     if (!((REGMEM|BITS32) & ~regflags))
  81.     return reg32[regval];
  82.     if (!(REG_SREG & ~regflags))
  83.     return sreg[regval];
  84.     if (!(REG_CREG & ~regflags))
  85.     return creg[regval];
  86.     if (!(REG_DREG & ~regflags))
  87.     return dreg[regval];
  88.     if (!(REG_TREG & ~regflags))
  89.     return treg[regval];
  90.     if (!(FPUREG & ~regflags))
  91.     return fpureg[regval];
  92.     if (!(MMXREG & ~regflags))
  93.     return mmxreg[regval];
  94.     return 0;
  95. }
  96.  
  97. static char *whichcond(int condval) {
  98.     static int conds[] = {
  99.     C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A,
  100.     C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G
  101.     };
  102.     return conditions[conds[condval]];
  103. }
  104.  
  105. /*
  106.  * Process an effective address (ModRM) specification.
  107.  */
  108. static unsigned char *do_ea (unsigned char *data, int modrm, int asize,
  109.                  int segsize, operand *op) {
  110.     int mod, rm, scale, index, base;
  111.  
  112.     mod = (modrm >> 6) & 03;
  113.     rm = modrm & 07;
  114.  
  115.     if (mod == 3) {               /* pure register version */
  116.     op->basereg = rm;
  117.     op->segment |= SEG_RMREG;
  118.     return data;
  119.     }
  120.  
  121.     op->addr_size = 0;
  122.  
  123.     if (asize == 16) {
  124.     /*
  125.      * <mod> specifies the displacement size (none, byte or
  126.      * word), and <rm> specifies the register combination.
  127.      * Exception: mod=0,rm=6 does not specify [BP] as one might
  128.      * expect, but instead specifies [disp16].
  129.      */
  130.     op->indexreg = op->basereg = -1;
  131.     op->scale = 1;               /* always, in 16 bits */
  132.     switch (rm) {
  133.       case 0: op->basereg = R_BX; op->indexreg = R_SI; break;
  134.       case 1: op->basereg = R_BX; op->indexreg = R_DI; break;
  135.       case 2: op->basereg = R_BP; op->indexreg = R_SI; break;
  136.       case 3: op->basereg = R_BP; op->indexreg = R_DI; break;
  137.       case 4: op->basereg = R_SI; break;
  138.       case 5: op->basereg = R_DI; break;
  139.       case 6: op->basereg = R_BP; break;
  140.       case 7: op->basereg = R_BX; break;
  141.     }
  142.     if (rm == 6 && mod == 0) {     /* special case */
  143.         op->basereg = -1;
  144.         if (segsize != 16)
  145.         op->addr_size = 16;
  146.         mod = 2;               /* fake disp16 */
  147.     }
  148.     switch (mod) {
  149.       case 0:
  150.         op->segment |= SEG_NODISP;
  151.         break;
  152.       case 1:
  153.         op->segment |= SEG_DISP8;
  154.         op->offset = (signed char) *data++;
  155.         break;
  156.       case 2:
  157.         op->segment |= SEG_DISP16;
  158.         op->offset = *data++;
  159.         op->offset |= (*data++) << 8;
  160.         break;
  161.     }
  162.     return data;
  163.     } else {
  164.     /*
  165.      * Once again, <mod> specifies displacement size (this time
  166.      * none, byte or *dword*), while <rm> specifies the base
  167.      * register. Again, [EBP] is missing, replaced by a pure
  168.      * disp32 (this time that's mod=0,rm=*5*). However, rm=4
  169.      * indicates not a single base register, but instead the
  170.      * presence of a SIB byte...
  171.      */
  172.     op->indexreg = -1;
  173.     switch (rm) {
  174.       case 0: op->basereg = R_EAX; break;
  175.       case 1: op->basereg = R_ECX; break;
  176.       case 2: op->basereg = R_EDX; break;
  177.       case 3: op->basereg = R_EBX; break;
  178.       case 5: op->basereg = R_EBP; break;
  179.       case 6: op->basereg = R_ESI; break;
  180.       case 7: op->basereg = R_EDI; break;
  181.     }
  182.     if (rm == 5 && mod == 0) {
  183.         op->basereg = -1;
  184.         if (segsize != 32)
  185.         op->addr_size = 32;
  186.         mod = 2;               /* fake disp32 */
  187.     }
  188.     if (rm == 4) {               /* process SIB */
  189.         scale = (*data >> 6) & 03;
  190.         index = (*data >> 3) & 07;
  191.         base = *data & 07;
  192.         data++;
  193.  
  194.         op->scale = 1 << scale;
  195.         switch (index) {
  196.           case 0: op->indexreg = R_EAX; break;
  197.           case 1: op->indexreg = R_ECX; break;
  198.           case 2: op->indexreg = R_EDX; break;
  199.           case 3: op->indexreg = R_EBX; break;
  200.           case 4: op->indexreg = -1; break;
  201.           case 5: op->indexreg = R_EBP; break;
  202.           case 6: op->indexreg = R_ESI; break;
  203.           case 7: op->indexreg = R_EDI; break;
  204.         }
  205.  
  206.         switch (base) {
  207.           case 0: op->basereg = R_EAX; break;
  208.           case 1: op->basereg = R_ECX; break;
  209.           case 2: op->basereg = R_EDX; break;
  210.           case 3: op->basereg = R_EBX; break;
  211.           case 4: op->basereg = R_ESP; break;
  212.           case 6: op->basereg = R_ESI; break;
  213.           case 7: op->basereg = R_EDI; break;
  214.           case 5:
  215.         if (mod == 0) {
  216.             mod = 2;
  217.             op->basereg = -1;
  218.         } else
  219.             op->basereg = R_EBP;
  220.         break;
  221.         }
  222.     }
  223.     switch (mod) {
  224.       case 0:
  225.         op->segment |= SEG_NODISP;
  226.         break;
  227.       case 1:
  228.         op->segment |= SEG_DISP8;
  229.         op->offset = (signed char) *data++;
  230.         break;
  231.       case 2:
  232.         op->segment |= SEG_DISP32;
  233.         op->offset = *data++;
  234.         op->offset |= (*data++) << 8;
  235.         op->offset |= ((long) *data++) << 16;
  236.         op->offset |= ((long) *data++) << 24;
  237.         break;
  238.     }
  239.     return data;
  240.     }
  241. }
  242.  
  243. /*
  244.  * Determine whether the code string in r corresponds to the data
  245.  * stream in data. Return the number of bytes matched if so.
  246.  */
  247. static int matches (unsigned char *r, unsigned char *data, int asize,
  248.             int osize, int segsize, insn *ins) {
  249.     unsigned char *origdata = data;
  250.     int a_used = FALSE, o_used = FALSE;
  251.  
  252.     while (*r) {
  253.     int c = *r++;
  254.     if (c >= 01 && c <= 03) {
  255.         while (c--)
  256.         if (*r++ != *data++)
  257.             return FALSE;
  258.     }
  259.     if (c == 04) {
  260.         switch (*data++) {
  261.           case 0x07: ins->oprs[0].basereg = 0; break;
  262.           case 0x17: ins->oprs[0].basereg = 2; break;
  263.           case 0x1F: ins->oprs[0].basereg = 3; break;
  264.           default: return FALSE;
  265.         }
  266.     }
  267.     if (c == 05) {
  268.         switch (*data++) {
  269.           case 0xA1: ins->oprs[0].basereg = 4; break;
  270.           case 0xA9: ins->oprs[0].basereg = 5; break;
  271.           default: return FALSE;
  272.         }
  273.     }
  274.     if (c == 06) {
  275.         switch (*data++) {
  276.           case 0x06: ins->oprs[0].basereg = 0; break;
  277.           case 0x0E: ins->oprs[0].basereg = 1; break;
  278.           case 0x16: ins->oprs[0].basereg = 2; break;
  279.           case 0x1E: ins->oprs[0].basereg = 3; break;
  280.           default: return FALSE;
  281.         }
  282.     }
  283.     if (c == 07) {
  284.         switch (*data++) {
  285.           case 0xA0: ins->oprs[0].basereg = 4; break;
  286.           case 0xA8: ins->oprs[0].basereg = 5; break;
  287.           default: return FALSE;
  288.         }
  289.     }
  290.     if (c >= 010 && c <= 012) {
  291.         int t = *r++, d = *data++;
  292.         if (d < t || d > t+7)
  293.         return FALSE;
  294.         else {
  295.         ins->oprs[c-010].basereg = d-t;
  296.         ins->oprs[c-010].segment |= SEG_RMREG;
  297.         }
  298.     }
  299.     if (c == 017)
  300.         if (*data++)
  301.         return FALSE;
  302.     if (c >= 014 && c <= 016) {
  303.         ins->oprs[c-014].offset = (signed char) *data++;
  304.         ins->oprs[c-014].segment |= SEG_SIGNED;
  305.     }
  306.     if (c >= 020 && c <= 022)
  307.         ins->oprs[c-020].offset = *data++;
  308.     if (c >= 024 && c <= 026)
  309.         ins->oprs[c-024].offset = *data++;
  310.     if (c >= 030 && c <= 032) {
  311.         ins->oprs[c-030].offset = *data++;
  312.         ins->oprs[c-030].offset |= (*data++ << 8);
  313.     }
  314.     if (c >= 034 && c <= 036) {
  315.         ins->oprs[c-034].offset = *data++;
  316.         ins->oprs[c-034].offset |= (*data++ << 8);
  317.         if (asize == 32) {
  318.         ins->oprs[c-034].offset |= (((long) *data++) << 16);
  319.         ins->oprs[c-034].offset |= (((long) *data++) << 24);
  320.         }
  321.         if (segsize != asize)
  322.         ins->oprs[c-034].addr_size = asize;
  323.     }
  324.     if (c >= 040 && c <= 042) {
  325.         ins->oprs[c-040].offset = *data++;
  326.         ins->oprs[c-040].offset |= (*data++ << 8);
  327.         ins->oprs[c-040].offset |= (((long) *data++) << 16);
  328.         ins->oprs[c-040].offset |= (((long) *data++) << 24);
  329.     }
  330.     if (c >= 050 && c <= 052) {
  331.         ins->oprs[c-050].offset = (signed char) *data++;
  332.         ins->oprs[c-050].segment |= SEG_RELATIVE;
  333.     }
  334.     if (c >= 060 && c <= 062) {
  335.         ins->oprs[c-060].offset = *data++;
  336.         ins->oprs[c-060].offset |= (*data++ << 8);
  337.         ins->oprs[c-060].segment |= SEG_RELATIVE;
  338.         ins->oprs[c-060].segment &= ~SEG_32BIT;
  339.     }
  340.     if (c >= 064 && c <= 066) {
  341.         ins->oprs[c-064].offset = *data++;
  342.         ins->oprs[c-064].offset |= (*data++ << 8);
  343.         if (asize == 32) {
  344.         ins->oprs[c-064].offset |= (((long) *data++) << 16);
  345.         ins->oprs[c-064].offset |= (((long) *data++) << 24);
  346.         ins->oprs[c-064].segment |= SEG_32BIT;
  347.         } else
  348.         ins->oprs[c-064].segment &= ~SEG_32BIT;
  349.         ins->oprs[c-064].segment |= SEG_RELATIVE;
  350.         if (segsize != asize)
  351.         ins->oprs[c-064].addr_size = asize;
  352.     }
  353.     if (c >= 070 && c <= 072) {
  354.         ins->oprs[c-070].offset = *data++;
  355.         ins->oprs[c-070].offset |= (*data++ << 8);
  356.         ins->oprs[c-070].offset |= (((long) *data++) << 16);
  357.         ins->oprs[c-070].offset |= (((long) *data++) << 24);
  358.         ins->oprs[c-070].segment |= SEG_32BIT | SEG_RELATIVE;
  359.     }
  360.     if (c >= 0100 && c <= 0177) {
  361.         int modrm = *data++;
  362.         ins->oprs[c & 07].basereg = (modrm >> 3) & 07;
  363.         ins->oprs[c & 07].segment |= SEG_RMREG;
  364.         data = do_ea (data, modrm, asize, segsize,
  365.               &ins->oprs[(c >> 3) & 07]);
  366.     }
  367.     if (c >= 0200 && c <= 0277) {
  368.         int modrm = *data++;
  369.         if (((modrm >> 3) & 07) != (c & 07))
  370.         return FALSE;           /* spare field doesn't match up */
  371.         data = do_ea (data, modrm, asize, segsize,
  372.               &ins->oprs[(c >> 3) & 07]);
  373.     }
  374.     if (c >= 0300 && c <= 0302) {
  375.         if (asize)
  376.         ins->oprs[c-0300].segment |= SEG_32BIT;
  377.         else
  378.         ins->oprs[c-0300].segment &= ~SEG_32BIT;
  379.         a_used = TRUE;
  380.     }
  381.     if (c == 0310) {
  382.         if (asize == 32)
  383.         return FALSE;
  384.         else
  385.         a_used = TRUE;
  386.     }
  387.     if (c == 0311) {
  388.         if (asize == 16)
  389.         return FALSE;
  390.         else
  391.         a_used = TRUE;
  392.     }
  393.     if (c == 0312) {
  394.         if (asize != segsize)
  395.         return FALSE;
  396.         else
  397.         a_used = TRUE;
  398.     }
  399.     if (c == 0320) {
  400.         if (osize == 32)
  401.         return FALSE;
  402.         else
  403.         o_used = TRUE;
  404.     }
  405.     if (c == 0321) {
  406.         if (osize == 16)
  407.         return FALSE;
  408.         else
  409.         o_used = TRUE;
  410.     }
  411.     if (c == 0322) {
  412.         if (osize != segsize)
  413.         return FALSE;
  414.         else
  415.         o_used = TRUE;
  416.     }
  417.     if (c == 0330) {
  418.         int t = *r++, d = *data++;
  419.         if (d < t || d > t+15)
  420.         return FALSE;
  421.         else
  422.         ins->condition = d - t;
  423.     }
  424.     }
  425.  
  426.     /*
  427.      * Check for unused a/o prefixes.
  428.      */
  429.     ins->nprefix = 0;
  430.     if (!a_used && asize != segsize)
  431.     ins->prefixes[ins->nprefix++] = (asize == 16 ? P_A16 : P_A32);
  432.     if (!o_used && osize != segsize)
  433.     ins->prefixes[ins->nprefix++] = (osize == 16 ? P_O16 : P_O32);
  434.  
  435.     return data - origdata;
  436. }
  437.  
  438. long disasm (unsigned char *data, char *output, int segsize, long offset,
  439.          int autosync) {
  440.     struct itemplate **p;
  441.     int length = 0;
  442.     char *segover;
  443.     int rep, lock, asize, osize, i, slen, colon;
  444.     unsigned char *origdata;
  445.     int works;
  446.     insn ins;
  447.  
  448.     /*
  449.      * Scan for prefixes.
  450.      */
  451.     asize = osize = segsize;
  452.     segover = NULL;
  453.     rep = lock = 0;
  454.     origdata = data;
  455.     for (;;) {
  456.     if (*data == 0xF3 || *data == 0xF2)
  457.         rep = *data++;
  458.     else if (*data == 0xF0)
  459.         lock = *data++;
  460.     else if (*data == 0x2E || *data == 0x36 || *data == 0x3E ||
  461.          *data == 0x26 || *data == 0x64 || *data == 0x65) {
  462.         switch (*data++) {
  463.           case 0x2E: segover = "cs"; break;
  464.           case 0x36: segover = "ss"; break;
  465.           case 0x3E: segover = "ds"; break;
  466.           case 0x26: segover = "es"; break;
  467.           case 0x64: segover = "fs"; break;
  468.           case 0x65: segover = "gs"; break;
  469.         }
  470.     } else if (*data == 0x66)
  471.         osize = 48 - segsize, data++;
  472.     else if (*data == 0x67)
  473.         asize = 48 - segsize, data++;
  474.     else
  475.         break;
  476.     }
  477.  
  478.     ins.oprs[0].segment = ins.oprs[1].segment = ins.oprs[2].segment =
  479.     ins.oprs[0].addr_size = ins.oprs[1].addr_size = ins.oprs[2].addr_size =
  480.     (segsize == 16 ? 0 : SEG_32BIT);
  481.     ins.condition = -1;
  482.     works = TRUE;
  483.     for (p = itable[*data]; *p; p++)
  484.     if ( (length = matches((unsigned char *)((*p)->code), data,
  485.                    asize, osize, segsize, &ins)) ) {
  486.         works = TRUE;
  487.         /*
  488.          * Final check to make sure the types of r/m match up.
  489.          */
  490.         for (i = 0; i < (*p)->operands; i++)
  491.         if (((ins.oprs[i].segment & SEG_RMREG) &&
  492.              !(MEMORY & ~(*p)->opd[i])) ||
  493.             (!(ins.oprs[i].segment & SEG_RMREG) &&
  494.              !(REGNORM & ~(*p)->opd[i]) &&
  495.              !((*p)->opd[i] & REG_SMASK)))
  496.             works = FALSE;
  497.         if (works)
  498.         break;
  499.     }
  500.     if (!length || !works)
  501.     return 0;               /* no instruction was matched */
  502.  
  503.     slen = 0;
  504.  
  505.     if (rep) {
  506.     slen += sprintf(output+slen, "rep%s ",
  507.             (rep == 0xF2 ? "ne" :
  508.              (*p)->opcode == I_CMPSB ||
  509.              (*p)->opcode == I_CMPSW ||
  510.              (*p)->opcode == I_CMPSD ||
  511.              (*p)->opcode == I_SCASB ||
  512.              (*p)->opcode == I_SCASW ||
  513.              (*p)->opcode == I_SCASD ? "e" : ""));
  514.     }
  515.     if (lock)
  516.     slen += sprintf(output+slen, "lock ");
  517.     for (i = 0; i < ins.nprefix; i++)
  518.     switch (ins.prefixes[i]) {
  519.       case P_A16: slen += sprintf(output+slen, "a16 "); break;
  520.       case P_A32: slen += sprintf(output+slen, "a32 "); break;
  521.       case P_O16: slen += sprintf(output+slen, "o16 "); break;
  522.       case P_O32: slen += sprintf(output+slen, "o32 "); break;
  523.     }
  524.  
  525.     for (i = 0; i < elements(ico); i++)
  526.     if ((*p)->opcode == ico[i]) {
  527.         slen += sprintf(output+slen, "%s%s", icn[i],
  528.                 whichcond(ins.condition));
  529.         break;
  530.     }
  531.     if (i >= elements(ico))
  532.     slen += sprintf(output+slen, "%s", insn_names[(*p)->opcode]);
  533.     colon = FALSE;
  534.     length += data - origdata;           /* fix up for prefixes */
  535.     for (i=0; i<(*p)->operands; i++) {
  536.     output[slen++] = (colon ? ':' : i==0 ? ' ' : ',');
  537.  
  538.     if (ins.oprs[i].segment & SEG_RELATIVE) {
  539.         ins.oprs[i].offset += offset + length;
  540.         /*
  541.          * sort out wraparound
  542.          */
  543.         if (!(ins.oprs[i].segment & SEG_32BIT))
  544.         ins.oprs[i].offset &= 0xFFFF;
  545.         /*
  546.          * add sync marker, if autosync is on
  547.          */
  548.         if (autosync)
  549.         add_sync (ins.oprs[i].offset, 0L);
  550.     }
  551.  
  552.     if ((*p)->opd[i] & COLON)
  553.         colon = TRUE;
  554.     else
  555.         colon = FALSE;
  556.  
  557.     if (((*p)->opd[i] & (REGISTER | FPUREG)) ||
  558.         (ins.oprs[i].segment & SEG_RMREG)) {
  559.         ins.oprs[i].basereg = whichreg ((*p)->opd[i],
  560.                         ins.oprs[i].basereg);
  561.         slen += sprintf(output+slen, "%s",
  562.                 reg_names[ins.oprs[i].basereg]);
  563.     } else if (!(UNITY & ~(*p)->opd[i])) {
  564.         output[slen++] = '1';
  565.     } else if ( (*p)->opd[i] & IMMEDIATE ) {
  566.         if ( (*p)->opd[i] & BITS8 ) {
  567.         slen += sprintf(output+slen, "byte ");
  568.         if (ins.oprs[i].segment & SEG_SIGNED) {
  569.             if (ins.oprs[i].offset < 0) {
  570.             ins.oprs[i].offset *= -1;
  571.             output[slen++] = '-';
  572.             } else
  573.             output[slen++] = '+';
  574.         }
  575.         } else if ( (*p)->opd[i] & BITS16 ) {
  576.         slen += sprintf(output+slen, "word ");
  577.         } else if ( (*p)->opd[i] & BITS32 ) {
  578.         slen += sprintf(output+slen, "dword ");
  579.         } else if ( (*p)->opd[i] & NEAR ) {
  580.         slen += sprintf(output+slen, "near ");
  581.         } else if ( (*p)->opd[i] & SHORT ) {
  582.         slen += sprintf(output+slen, "short ");
  583.         }
  584.         slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset);
  585.     } else if ( !(MEM_OFFS & ~(*p)->opd[i]) ) {
  586.         slen += sprintf(output+slen, "[%s%s%s0x%lx]",
  587.                 (segover ? segover : ""),
  588.                 (segover ? ":" : ""),
  589.                 (ins.oprs[i].addr_size == 32 ? "dword " :
  590.                  ins.oprs[i].addr_size == 16 ? "word " : ""),
  591.                 ins.oprs[i].offset);
  592.         segover = NULL;
  593.     } else if ( !(REGMEM & ~(*p)->opd[i]) ) {
  594.         int started = FALSE;
  595.         if ( (*p)->opd[i] & BITS8 )
  596.         slen += sprintf(output+slen, "byte ");
  597.         if ( (*p)->opd[i] & BITS16 )
  598.         slen += sprintf(output+slen, "word ");
  599.         if ( (*p)->opd[i] & BITS32 )
  600.         slen += sprintf(output+slen, "dword ");
  601.         if ( (*p)->opd[i] & BITS64 )
  602.         slen += sprintf(output+slen, "qword ");
  603.         if ( (*p)->opd[i] & BITS80 )
  604.         slen += sprintf(output+slen, "tword ");
  605.         if ( (*p)->opd[i] & FAR )
  606.         slen += sprintf(output+slen, "far ");
  607.         if ( (*p)->opd[i] & NEAR )
  608.         slen += sprintf(output+slen, "near ");
  609.         output[slen++] = '[';
  610.         if (ins.oprs[i].addr_size)
  611.         slen += sprintf(output+slen, "%s",
  612.                 (ins.oprs[i].addr_size == 32 ? "dword " :
  613.                  ins.oprs[i].addr_size == 16 ? "word " : ""));
  614.         if (segover) {
  615.         slen += sprintf(output+slen, "%s:", segover);
  616.         segover = NULL;
  617.         }
  618.         if (ins.oprs[i].basereg != -1) {
  619.         slen += sprintf(output+slen, "%s",
  620.                 reg_names[ins.oprs[i].basereg]);
  621.         started = TRUE;
  622.         }
  623.         if (ins.oprs[i].indexreg != -1) {
  624.         if (started)
  625.             output[slen++] = '+';
  626.         slen += sprintf(output+slen, "%s",
  627.                 reg_names[ins.oprs[i].indexreg]);
  628.         if (ins.oprs[i].scale > 1)
  629.             slen += sprintf(output+slen, "*%d", ins.oprs[i].scale);
  630.         started = TRUE;
  631.         }
  632.         if (ins.oprs[i].segment & SEG_DISP8) {
  633.         int sign = '+';
  634.         if (ins.oprs[i].offset & 0x80) {
  635.             ins.oprs[i].offset = - (signed char) ins.oprs[i].offset;
  636.             sign = '-';
  637.         }
  638.         slen += sprintf(output+slen, "%c0x%lx", sign,
  639.                 ins.oprs[i].offset);
  640.         } else if (ins.oprs[i].segment & SEG_DISP16) {
  641.         if (started)
  642.             output[slen++] = '+';
  643.         slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset);
  644.         } else if (ins.oprs[i].segment & SEG_DISP32) {
  645.         if (started)
  646.             output[slen++] = '+';
  647.         slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset);
  648.         }
  649.         output[slen++] = ']';
  650.     } else {
  651.         slen += sprintf(output+slen, "<operand%d>", i);
  652.     }
  653.     }
  654.     output[slen] = '\0';
  655.     if (segover) {               /* unused segment override */
  656.     char *p = output;
  657.     int count = slen+1;
  658.     while (count--)
  659.         p[count+3] = p[count];
  660.     strncpy (output, segover, 2);
  661.     output[2] = ' ';
  662.     }
  663.     return length;
  664. }
  665.  
  666. long eatbyte (unsigned char *data, char *output) {
  667.     sprintf(output, "db 0x%02X", *data);
  668.     return 1;
  669. }
  670.